home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 August: Tool Chest / Dev.CD Aug 00 TC Disk 2.toast / pc / sample code / printing / dropprint usb / testprinterclass.c < prev    next >
Encoding:
Text File  |  2000-06-23  |  11.2 KB  |  361 lines

  1. // File TestPrinterClass.c
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <types.h>
  7.  
  8. #include <gestalt.h>
  9. #include <errors.h>
  10.  
  11. #ifndef __DIALOGS__
  12. #include <Dialogs.h>
  13. #endif
  14. #ifndef __EVENTS__
  15. #include <Events.h>
  16. #endif
  17. #ifndef __FILES__
  18. #include <Files.h>
  19. #endif
  20. #ifndef __DEVICES__
  21. #include <Devices.h>
  22. #endif
  23. #include <textedit.h>
  24.  
  25. #ifndef __NUMBERFORMATTING__
  26. #include <numberformatting.h>
  27. #endif
  28.  
  29. #include "TestPrinterClass.h"
  30. #include "SafeNameRegistry.h"
  31.  
  32. enum {
  33.     kUSBNoErr                    = 0,
  34.     kUSBNoTran                    = 0,
  35.     kUSBNoDelay                    = 0,
  36.     kUSBPending                    = 1,                            /* */
  37.                                                                 /* USB assigned error numbers in range -6900 .. -6999 */
  38.     kUSBBaseError                = -7000,                        /* */
  39.                                                                 /* USB Services Errors */
  40.     kUSBInternalErr                = -6999,                        /* Internal error */
  41.     kUSBUnknownDeviceErr        = -6998,                        /*  device ref not recognised */
  42.     kUSBUnknownPipeErr            = -6997,                        /*  Pipe ref not recognised */
  43.     kUSBTooManyPipesErr            = -6996,                        /*  Too many pipes */
  44.     kUSBIncorrectTypeErr        = -6995,                        /*  Incorrect type */
  45.     kUSBRqErr                    = -6994,                        /*  Request error */
  46.     kUSBUnknownRequestErr        = -6993,                        /*  Unknown request */
  47.     kUSBTooManyTransactionsErr    = -6992,                        /*  Too many transactions */
  48.     kUSBAlreadyOpenErr            = -6991,                        /*  Already open */
  49.     kUSBNoDeviceErr                = -6990,                        /*  No device */
  50.     kUSBDeviceErr                = -6989,                        /*  Device error */
  51.     kUSBOutOfMemoryErr            = -6988,                        /*  Out of memory */
  52.     kUSBNotFound                = -6987,                        /*  Not found */
  53.     kUSBPBVersionError            = -6986,                        /*  Wrong pbVersion */
  54.     kUSBPBLengthError            = -6985,                        /*  pbLength too small */
  55.     kUSBCompletionError            = -6984,                        /*  no completion routine specified */
  56.     kUSBFlagsError                = -6983,                        /*  Flags not zeroed */
  57.     kUSBAbortedError            = -6982,                        /*  Pipe aborted */
  58.     kUSBNoBandwidthError        = -6981,                        /*  Not enough bandwidth available */
  59.     kUSBPipeIdleError            = -6980,                        /*  Pipe is Idle, it will not accept transactions */
  60.     kUSBPipeStalledError        = -6979,                        /*  Pipe has stalled, error needs to be cleared */
  61.     kUSBUnknownInterfaceErr        = -6978,                        /*  Interface ref not recognised */
  62.                                                                 /* */
  63.                                                                 /* USB Manager Errors */
  64.     kUSBBadDispatchTable        = -6950,                        /* Improper driver dispatch table */
  65.                                                                 /* */
  66.                                                                 /* Hardware Errors */
  67.                                                                 /* Note pipe stalls are communication */
  68.                                                                 /* errors. The affected pipe can not */
  69.                                                                 /* be used until USBClearPipeStallByReference  */
  70.                                                                 /* is used */
  71.                                                                 /* kUSBEndpointStallErr is returned in */
  72.                                                                 /* response to a stall handshake */
  73.                                                                 /* from a device. The device has to be */
  74.                                                                 /* cleared before a USBClearPipeStallByReference */
  75.                                                                 /* can be used */
  76.     kUSBLinkErr                    = -6916,
  77.     kUSBCRCErr                    = -6915,                        /*  Pipe stall, bad CRC */
  78.     kUSBBitstufErr                = -6914,                        /*  Pipe stall, bitstuffing */
  79.     kUSBDataToggleErr            = -6913,                        /*  Pipe stall, Bad data toggle */
  80.     kUSBEndpointStallErr        = -6912,                        /*  Device didn't understand */
  81.     kUSBNotRespondingErr        = -6911,                        /*  Pipe stall, No device, device hung */
  82.     kUSBPIDCheckErr                = -6910,                        /*  Pipe stall, PID CRC error */
  83.     kUSBWrongPIDErr                = -6909,                        /*  Pipe stall, Bad or wrong PID */
  84.     kUSBOverRunErr                = -6908,                        /*  Packet too large or more data than buffer */
  85.     kUSBUnderRunErr                = -6907,                        /*  Less data than buffer */
  86.     kUSBRes1Err                    = -6906,
  87.     kUSBRes2Err                    = -6905,
  88.     kUSBBufOvrRunErr            = -6904,                        /*  Host hardware failure on data in, PCI busy? */
  89.     kUSBBufUnderRunErr            = -6903,                        /*  Host hardware failure on data out, PCI busy? */
  90.     kUSBNotSent1Err                = -6902,                        /*  Transaction not sent */
  91.     kUSBNotSent2Err                = -6901                            /*  Transaction not sent */
  92. };
  93.  
  94. #define SECONDS( n )            (n*60)
  95. #define PROGRAM                "DropPrint•USB"
  96. #define kStrPrinterClass    PROGRAM ": "
  97.  
  98. enum {
  99.     kStatusDialog = 513
  100. };
  101.  
  102. enum {
  103.     kStatusBarItem = 1
  104. };
  105.  
  106.  
  107. char                *outbuffer = NULL;
  108. IOParam            fsendblk;
  109. unsigned long    fUSBReference;
  110. char                *filename;
  111. DialogPtr        gStatusDlg;
  112.  
  113. void        dump( char *p, long count );
  114. OSErr        sendfile( char *sourcefile, long buffersize );
  115. OSStatus OpenClassDriver( char *which_printer );
  116. void        showstatus( long current, long endfile );
  117.  
  118. void
  119. dump( char *p, long count )
  120. {
  121.     char    *q, *e, *f,
  122.             *d, line[64+32+1+1];    //2bytes per hex, 1 byte per char, 1 tab, 1 nul
  123.     short    nibble;
  124.  
  125.     while ( count > 0 )
  126.     {
  127.         q = p;                                    // start of line
  128.         e = p + 32;                                // proposed end of line
  129.         f = p + (count > 32? 32: count);    // actual end of line
  130.         d = line;
  131.         //
  132.         //    standard hex dump
  133.         //
  134.         for ( ; count > 0 && p < e; ++p, --count )
  135.         {
  136.             nibble = (*p >> 4) & 0x0F;
  137.             *d++ = nibble + (nibble > 9? 'A' - 10:'0');
  138.             nibble = *p & 0x0F;
  139.             *d++ = nibble + (nibble > 9? 'A' - 10:'0');
  140.         }
  141.         for ( ; p < e; ++p )
  142.         {
  143.             *d++ = ' ';
  144.             *d++ = ' ';
  145.         }
  146.         *d++ = '\t';
  147.         //
  148.         //    ascii sidebar
  149.         //
  150.         for ( p = q; p < f; ++p )
  151.             *d++ = *p < ' ' || *p >= 0x7F? '.': *p;
  152.         *d = '\0';
  153.         fprintf( stderr, "%s\n", line );
  154.     }
  155. }
  156.  
  157. OSStatus
  158. OpenClassDriver( char *which_printer )
  159. {
  160.     Str255            driverName;        // unit table driver name
  161.     OSStatus            err = -192;        // resNotFound
  162.     RegEntryID        self;
  163.     unsigned long    length;
  164.     
  165.     
  166.     fsendblk.ioRefNum = -1;                    // preload our IOParms in engvars
  167.     fsendblk.ioResult = 0;
  168.     fsendblk.ioCompletion = 0L;
  169.  
  170.     err = SafeRegistryEntryIDInit( &self );
  171.     if ( err == noErr )
  172.     {
  173.     
  174.         err = SafeRegistryCStrEntryLookup( nil, which_printer, &self );
  175.  
  176.         length = sizeof(driverName);
  177.         if ( err == noErr )
  178.             err = SafeRegistryPropertyGet( &self, "drvrOut", &driverName, &length );
  179.         if ( err == noErr )
  180.             err = OpenDriver( driverName, &fsendblk.ioRefNum );
  181.  
  182.         length = sizeof(fUSBReference);
  183.         if ( err == noErr )
  184.             err = SafeRegistryPropertyGet( &self, "privateData", &fUSBReference, &length );
  185.  
  186.         SafeRegistryEntryIDDispose(&self);
  187.     }
  188.  
  189.     return err;
  190. }
  191.  
  192. void
  193. showstatus( long current, long endfile )
  194. {
  195.     GrafPtr    oldport;
  196.     Rect        r;
  197.     Handle    h;
  198.     short        type;
  199.     long        width;
  200.     char        info[526];
  201.     
  202.     GetPort( &oldport );
  203.     SetPort( gStatusDlg );
  204.     GetDialogItem( gStatusDlg, kStatusBarItem, &type, &h, &r );
  205.     
  206.     // we have, width/ (r.right - r.left) == current/endfile
  207.     width = current *(r.right - r.left);
  208.     width /= endfile;
  209.     
  210.     FrameRect( &r );
  211.  
  212.     InsetRect( &r, 1, 1 );
  213.     sprintf( info, "%ld of %ld", current, endfile );
  214.     TETextBox( info, strlen(info), &r, teJustCenter );
  215.  
  216.     r.right = width + r.left;
  217.     InvertRect( &r );
  218.     
  219.     SetPort( oldport );
  220. }
  221.  
  222. OSErr
  223. sendfile( char *sourcefile, long buffersize )
  224. {
  225.     FILE                 *fin = fopen( sourcefile, "rb" );
  226.     long                count;
  227.     EventRecord        e;
  228.     OSStatus            err;
  229.     long                eoffin;    // length of input file
  230.     
  231.     gStatusDlg = GetNewDialog( kStatusDialog, nil, (WindowPtr)-1);
  232.  
  233.     if ( !fin )
  234.         err = fnfErr;        // cant open file
  235.     else
  236.     {
  237.         fseek( fin, 0, 2 /*fsFromEnd*/ );
  238.         eoffin = ftell( fin );
  239.         fseek( fin, 0, 0 /*fsFromStart*/ );
  240.         do {
  241.             count = fread( outbuffer, sizeof(char), buffersize, fin );
  242.             if ( count <= 0 )
  243.                 break;
  244.         //    dump( outbuffer, count );
  245.  
  246.             fsendblk.ioBuffer = outbuffer;
  247.             fsendblk.ioReqCount = count;
  248.             err = PBWriteAsync( (ParamBlockRec*) &fsendblk );
  249.             if ( err != noErr )
  250.                 break;
  251.             showstatus( ftell( fin ), eoffin );
  252.  
  253.             // wait for i/o to complete
  254.             while ( fsendblk.ioResult == 1 )
  255.             {
  256.                 WaitNextEvent( keyDownMask, &e, 0, NULL );
  257.                 if (e.what == keyDown && e.modifiers & cmdKey) {
  258.                     if ( (e.message & charCodeMask) == '.' )
  259.                         break;
  260.                 }
  261.             }
  262.             if ( fsendblk.ioResult != noErr )
  263.                 break;
  264.             // if user canceled, exit the download
  265.             WaitNextEvent( keyDownMask, &e, 0, NULL );
  266.             
  267.             if (e.what == keyDown && e.modifiers & cmdKey) {
  268.                 if ( (e.message & charCodeMask) == '.' )
  269.                     break;
  270.             }
  271.             
  272.         } while ( count > 0 );
  273.     
  274.         DisposeDialog(gStatusDlg);
  275.         if ( err == noErr && fsendblk.ioResult != noErr )
  276.             err = fsendblk.ioResult;
  277.         fclose( fin );
  278.     }
  279.     
  280.     return err;
  281. }
  282.  
  283. OSErr
  284. sendusb( char *printer_name, char *sourcefile, long blocksize, int repeat_count )
  285. {
  286.     OSStatus err = noErr;
  287.     outbuffer = (char *) malloc( blocksize );
  288.     memset( &fsendblk, 0, sizeof(fsendblk) );
  289.     
  290.     if ( !outbuffer )
  291.         err = iMemFullErr;    // memfull error
  292.     if ( err == noErr )
  293.         err = OpenClassDriver( printer_name );
  294.     if ( err == noErr )
  295.     {
  296.         for ( ; err == noErr && repeat_count > 0; --repeat_count )
  297.             err = sendfile( sourcefile, blocksize );
  298.  
  299.         if ( err != noErr )
  300.             KillIO( fsendblk.ioRefNum );
  301.             
  302.         if ( fsendblk.ioRefNum != -1 )
  303.             CloseDriver(fsendblk.ioRefNum);
  304.     }
  305.     if ( outbuffer )
  306.         free( outbuffer );
  307.     
  308.     if ( err != noErr )
  309.     {
  310.         unsigned char *p;
  311.         int                slen;
  312.         switch ( err )
  313.         {    
  314.             case  iMemFullErr:                         p = "\p" PROGRAM "Not enough memory. (Increase App heap, or use smaller block)"; break;
  315.             case    kUSBInternalErr:                    p = "\p" kStrPrinterClass "Internal error"; break;
  316.             case    kUSBUnknownDeviceErr:            p = "\p" kStrPrinterClass "Unknown device"; break;
  317.             case    kUSBUnknownPipeErr:                 p = "\p" kStrPrinterClass "Unknown pipe"; break;
  318.             case    kUSBTooManyPipesErr:                p = "\p" kStrPrinterClass "Too many pipes"; break;
  319.             case    kUSBIncorrectTypeErr:            p = "\p" kStrPrinterClass "Incorrect type"; break;
  320.             case    kUSBRqErr:                            p = "\p" kStrPrinterClass "Request error"; break;
  321.             case    kUSBUnknownRequestErr:            p = "\p" kStrPrinterClass "Unknown request"; break;
  322.             case    kUSBTooManyTransactionsErr:    p = "\p" kStrPrinterClass "Too many transactions"; break;
  323.             case    kUSBAlreadyOpenErr:                p = "\p" kStrPrinterClass "Already open"; break;
  324.             case    kUSBNoDeviceErr:                    p = "\p" kStrPrinterClass "No device"; break;
  325.             case    kUSBDeviceErr:                        p = "\p" kStrPrinterClass "Device error"; break;
  326.             case    kUSBOutOfMemoryErr:                p = "\p" kStrPrinterClass "Out of memory"; break;
  327.             case    kUSBNotFound:                        p = "\p" kStrPrinterClass "Not found"; break;
  328.             case    kUSBLinkErr:                        p = "\p" kStrPrinterClass "Link Err"; break;
  329.             case    kUSBCRCErr:                            p = "\p" kStrPrinterClass "Comms/Device err, bad CRC";  break;        
  330.             case    kUSBBitstufErr:                    p = "\p" kStrPrinterClass "Comms/Device err, bitstuffing"; break;        
  331.             case    kUSBDataToggleErr:                p = "\p" kStrPrinterClass "Comms/Device err, Bad data toggle"; break;        
  332.             case    kUSBEndpointStallErr:            p = "\p" kStrPrinterClass "Device didn't understand"; break;        
  333.             case    kUSBNotRespondingErr:            p = "\p" kStrPrinterClass "No device, device hung"; break;        
  334.             case    kUSBPIDCheckErr:                    p = "\p" kStrPrinterClass "Comms/Device err, PID CRC error"; break;        
  335.             case    kUSBWrongPIDErr:                    p = "\p" kStrPrinterClass "Comms/Device err, Bad or wrong PID"; break;        
  336.             case    kUSBOverRunErr:                    p = "\p" kStrPrinterClass "Packet too large or more data than buffer"; break;        
  337.             case    kUSBUnderRunErr:                    p = "\p" kStrPrinterClass "Less data than buffer"; break;        
  338.             case    kUSBRes1Err:                        p = "\p" kStrPrinterClass "kUSBRes1Err"; break;        
  339.             case    kUSBRes2Err:                        p = "\p" kStrPrinterClass "kUSBRes1Err"; break;        
  340.             case    kUSBBufOvrRunErr:                    p = "\p" kStrPrinterClass "Buffer over run error"; break;        
  341.             case    kUSBBufUnderRunErr:                p = "\p" kStrPrinterClass "Buffer under run error"; break;        
  342.             case    kUSBNotSent1Err:                    p = "\p" kStrPrinterClass "Transaction not sent1"; break;        
  343.             case    kUSBNotSent2Err:                    p = "\p" kStrPrinterClass "Transaction not sent2"; break;    
  344.             default:
  345.                 p = "\p" kStrPrinterClass "Unknown error nnnnnnnn";
  346.                 NumToString( err, p + *p - 8 );
  347.                 slen = *(p + *p - 8);
  348.                 *(p + *p - 8) = ' ';
  349.                 *p += slen - 8;
  350.                 break;
  351.         }
  352.         
  353.         ParamText( p, nil, nil, nil );
  354.         StopAlert( 768, nil );
  355.         err = noErr;
  356.     }
  357.     return err;
  358. }
  359.  
  360. /* eof */
  361.